/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.babeuf.form.conditions 
{
	import flash.events.EventDispatcher;
	import net.babeuf.form.event.FieldErrorEvent;
	import net.babeuf.form.messages.Messages;
	import net.babeuf.form.sensors.AbstractSensor;
	
	/**
	* Dispatched when en error is handled for the current condition
	* 
	* @eventType net.babeuf.form.event.FieldErrorEvent.FIELD_ERROR
	* @langversion 3.0
	* @playerversion Flash 9
	*/
	[Event(name="fieldError", type="net.babeuf.form.event.FieldErrorEvent")]
	
	/**
	 * Abstraction for extra form conditions.
	 * Conditions can support sensors like fields
	 * Extra conditions must implement ICondition and override match method. That's where the validation takes place
	 * 
	 * @langversion 3.0
	 * @playerversion Flash 9
	 * 
	 * @author damien pegoraro
	 */
	public class AbstractCondition extends EventDispatcher implements ICondition
	{
		/**
		 * Internal list of sensors linked to the condition
		 * 
		 * @see net.babeuf.form.sensors.AbstractSensor
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		protected var _sensors : Array ;
			
		/**
		 * Identifier for the condition
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public var name : String ;
		
		/**
		 *  The registered error code that will be be thrown when condition is not matched 
		 * 
		 * @see net.babeuf.form.messages.Messages
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public var errorCode : String = Messages.DEFAULT ; 
		
		
		/**
		 *  Creates a new instance
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public function AbstractCondition() 
		{
			_sensors = new Array() ; 
		}
		
		/**
		 * Add a <code>AbstractSensor</code> element for the current condition
		 * On condition check and fail, all sensors registered will react
		 * 
		 * @see net.babeuf.form.sensors.AbstractSensor
		 * 
		 * @param	sensor	the sensor to add for this condition
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public function addSensor( sensor : AbstractSensor ) : void
		{
			_sensors.push( sensor ) ; 
		}
		
		/**
		 * Dispose the element for garbage collection
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public function dispose() : void
		{
			for each ( var sensor : AbstractSensor in _sensors ) 
			{
				if ( sensor ) sensor.dispose() ; 
			}
			_sensors = null ; 
		}
		
		/**
		 * Reset the condition and all of its sensors
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public function empty()  :void
		{
			_updateSensors( true )   ;
		}
		
		/**
		 * Checks the condition. 
		 * 
		 * <p>This method must be overwritten by concrete classes for working custom conditions
		 * In custom conditions, you must also manualy <code>_updateSensors</code> to setup the sensors state.</p>
		 * 
		 * @return <code>true</code> is the condition is matched, <code>false</code> if not
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		public function match() : Boolean
		{
			return true ; 
		}
		
		/**
		 * Dispatch the condition error code id to registered listeners
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		protected function _throwError() : void
		{
			dispatchEvent( new FieldErrorEvent( FieldErrorEvent.FIELD_ERROR, null, errorCode ) ) ; 
		}
		
		/**
		 * Update all linked <code>AbstractSensor</code> state		 
		 * 
		 * @see net.babeuf.form.sensors.AbstractSensor
		 * 
		 * @param	ok  was the ckeck successful ( <code>true</code> ) or not
		 * 
		 * @langversion 3.0
		 * @playerversion Flash 9
		 */
		protected function _updateSensors( ok : Boolean  = true ) : void
		{
			for each ( var s:  AbstractSensor in _sensors ) 
			{
				if ( ok ) s.ok( ) ;
				else s.ko() ; 
			}
			if (  !ok ) _throwError() ; 
		}
		
	}

}